"""
PyMak rule and action to build Python files from CORBA IDL files.
This module is built on the PyMak version of pymak.

"""

# Python imports
import os
import py_compile
import zipfile
import sys
import logging

# PyMak imports
import pymak
from pymak.path import to_path

import pythoncompile

MAJOR_VERSION = 1
MINOR_VERSION = 0

def init(context):
    """This method sets up into the provided context the following:

    'PYIDL' property.
    'PYIDLFLAGS' property.

    The rule '.pyzipidl' bound to PyIDLZipRule, with the
    package_source set to True. Create your own instance of this rule
    if you need a different default.

    The action '.zip.py.idl' which is bound to a PyIDLZipAction instance.

    If the 'buildos' variant has not been defined yet, this variant is
    created.
    """
    
    new_variants = [
        ('buildos', ('win32', 'unix', 'linux'), 'win32'),
    ]
    context.variants.reconcile_all(pymak.variant.VariantValues(new_variants))

    context.define_property("PYIDL", [("buildos", "win32") ], "$(OMNIPY_HOME)/bin/x86_win32/omniidl")
    context.define_property("PYIDL", [("buildos", "linux") ], "$(OMNI_HOME)/bin/omniidl")
    context.define_property("PYIDLFLAGS", [ ], "-bpython")

    context.declare_rule('.pyzipidl', PyIDLZipRule(context))
    context.declare_action('.zip.py.idl', PyIDLZipAction())

    
def version_ok(major, minor):
    if major != MAJOR_VERSION:
        return False
    if minor > MINOR_VERSION:
        return False
    return True


class PyIDLZipRule(pymak.Rule):
    def __init__(self, context, package_source=True):
        super(PyIDLZipRule, self).__init__(context)
        self.package_source = package_source
        
    def apply_rule(self, target_name, **kwargs):
        pyidlzip = self.context.target(target_name,
                                       rule=None,
                                       variants=['buildos'],
                                       target_dir="build/pyidlzip/$(allvariants)",
                                       action=".zip.py.idl",
                                       attrs=dict(package_source=self.package_source),
                                       **kwargs)
        return pyidlzip
    

class PyIDLZipAction(pymak.CommandAction):
    def execute_action(self, t, variant_values):
        package_source = getattr(t, 'package_source', True)
        
        pyidl_dir = to_path("build/pyidl")
        if not pyidl_dir.exists(): # Force creation of build/pyidl directory
            pyidl_dir.makedirs()

        py_ver ="2.3"
        if t._implements_variants.contains('py'):
            py_ver = t._implements_variants.lookup('py')

        # Command to generate the py files
        exec_command = "$(PYIDL) $(PYIDLFLAGS) %s %s -C %s %s" % (
                    t._context.stringify_property("IDLINCLUDES", variant_values, "-I"),
                    t._context.stringify_property("VARIANT_DEFINES", variant_values, "-D"),
                    pyidl_dir,
                    t._depends_on.string_of_target_files(variant_values)
                    )

        # Generate the py files
        self._execute_action(exec_command, t, variant_values)

        # Now generate the pyc files
        pyfiles = list(pyidl_dir.walk("*.py"))
        for pyfile in pyfiles:
            logging.info(_("Compiling: '%s'"), pyfile)
            pythoncompile._compile_file(pyfile, py_ver, variant_values, t)

        # Finally zip the pyc files up
        zip = zipfile.ZipFile(t.path, "w")
        for pyfile in pyfiles:
            pyfile = pyfile.replace('\\', '/')
            arcname = str(pyfile[len(pyidl_dir)+1:len(pyfile)]) # + removes trailing /
            pycfile = pyfile + "c"
            logging.info(_("Adding file %s to archive as %s"), pycfile, arcname)
            zip.write(pycfile, arcname + "c")

            # delete the pyc file
            os.remove(pycfile)

            # zip the .py file in a src directory
            if package_source and not pymak.os_is_unix():
                arcname = "src/" + arcname
                logging.info(_("Adding file %s to archive as %s"), pyfile, arcname)
                zip.write(pyfile, arcname)
            
        zip.close()
